// -----------------------------------------------------------------------
//  <copyright file="DefaultCorsInitializer.cs" company="LiuliuSoft">
//      Copyright (c) 2022-2022 DaprPlus. All rights reserved.
//  </copyright>
//  <site>https://www.dapr.plus</site>
//  <last-editor>郭明锋</last-editor>
//  <last-date>2022-11-27 2:14</last-date>
// -----------------------------------------------------------------------

using Microsoft.AspNetCore.Cors.Infrastructure;


namespace DaprPlus.AspNetCore.Cors;

/// <summary>
/// 默认Cors初始化器
/// </summary>
public class DefaultCorsInitializer : ICorsInitializer
{
    private CorsOptions? _defaultOptions;
    private readonly List<string> _policyNames = [];

    /// <summary>
    /// 添加Cors
    /// </summary>
    public IServiceCollection AddCors(IServiceCollection services)
    {
        var configuration = services.GetConfiguration();
        if (configuration == null)
        {
            return services;
        }

        var list = new List<CorsOptions>();
        configuration.GetSection(CorsOptions.Position).Bind(list);
        if (list.Count == 0)
        {
            return services;
        }
        _defaultOptions = list.FirstOrDefault(m => m.Enabled && (string.IsNullOrEmpty(m.PolicyName)
            || m.PolicyName.Equals("default", StringComparison.OrdinalIgnoreCase)));

        services.AddCors(cors =>
        {
            if (_defaultOptions != null)
            {
                cors.AddDefaultPolicy(policy => AddPolicy(policy, _defaultOptions));
            }

            foreach (var item in list.Where(m => m.Enabled && !string.IsNullOrEmpty(m.PolicyName) && !m.PolicyName.Equals("default", StringComparison.OrdinalIgnoreCase)))
            {
                cors.AddPolicy(item.PolicyName!, policy => AddPolicy(policy, item));
                _policyNames.Add(item.PolicyName!);
            }
        });

        return services;
    }

    private static void AddPolicy(CorsPolicyBuilder policy, CorsOptions item)
    {
        if (item.AllowAnyOrigin)
        {
            policy.AllowAnyOrigin();
        }
        else if (item.WithOrigins != null)
        {
            policy.WithOrigins(item.WithOrigins);
        }
        if (item.AllowAnyHeader)
        {
            policy.AllowAnyHeader();
        }
        else if (item.WithHeaders != null)
        {
            policy.WithHeaders(item.WithHeaders);
        }

        if (item.AllowAnyMethod)
        {
            policy.AllowAnyMethod();
        }
        else if (item.WithMethods != null)
        {
            policy.WithMethods(item.WithMethods);
        }

        if (item is { AllowCredentials: true, AllowAnyOrigin: false })
        {
            policy.AllowCredentials();
        }
        else if (item.DisallowCredentials)
        {
            policy.DisallowCredentials();
        }
    }

    /// <summary>
    /// 应用Cors
    /// </summary>
    public IApplicationBuilder UseCors(IApplicationBuilder app)
    {
        if (_defaultOptions != null)
        {
            app.UseCors();
            foreach (var policyName in _policyNames)
            {
                app.UseCors(policyName);
            }
        }

        return app;
    }
}
